package com.ruoyi.api.activiti.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.ruoyi.activiti.domain.HistoricActivity;
import com.ruoyi.activiti.service.IProcessService;
import com.ruoyi.api.activiti.domain.ApplyAssetsReport;
import com.ruoyi.api.activiti.domain.ApproveProcessVo;
import com.ruoyi.api.activiti.domain.DailyWorkBaseVO;
import com.ruoyi.api.activiti.domain.ExpenseReport;
import com.ruoyi.api.applycopy.domain.Applycopy;
import com.ruoyi.api.applycopy.service.IApplycopyService;
import com.ruoyi.api.mqtt.MqttService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.projectUsers.domain.ProjectUsers;
import com.ruoyi.project.projectUsers.service.IProjectUsersService;
import com.ruoyi.system.cache.user.UserCacheService;
import com.ruoyi.system.domain.SysRole;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
@Slf4j
public class UsualWrokService {
  @Autowired
  private RuntimeService runtimeService;
  @Autowired
  private IdentityService identityService;
  @Autowired
  private TaskService taskService;
  @Autowired
  private HistoryService historyService;
  @Autowired
  private SysUserMapper userMapper;
  @Autowired
  private ExpenseReportService expenseReportService;
  @Autowired
  private ApplyAssetsReportService applyAssetsReportService;

  @Autowired
  private IProcessService processService;


  @Value("${wspaas.dailyworkUrl}")
  private String dwUrl;

  public String commit(JSONObject o) {
    StringBuilder sb = new StringBuilder();
    o.put("taskName", "未启动");
    o.put("suspendState", "0");
    String type = o.getString("type");
    if (type.equalsIgnoreCase("applyassets")) {
      o.put("typeName", "设备申请");
    } else if (type.equalsIgnoreCase("expense")) {
      o.put("typeName", "维修费用申请");
    }
    sb.append(dwUrl).append("/api/").append(type).append("/commit");
    return HttpClientUtil.doPost(sb.toString(), o);
  }

  public List<DailyWorkBaseVO> todoTasksMobile(String loginName, String queryService) {
    List<Task> list = taskService.createTaskQuery().includeProcessVariables().taskAssignee(loginName).list();
    List<Task> candidateList = taskService.createTaskQuery().
      includeProcessVariables().taskCandidateUser(loginName).list();
    List<Task> allList = Lists.newArrayList();
    allList.addAll(list);
    allList.addAll(candidateList);
    List<DailyWorkBaseVO> TodoList = new ArrayList<>();
    for (Task task : allList) {
      Map<String, Object> processVariables = task.getProcessVariables();
      String taskService = (String) processVariables.get("service");
      if (!StringUtils.isEmpty(queryService)) {
        if (!taskService.equalsIgnoreCase(queryService)) {
          continue;
        }
      }
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().
        processInstanceId(task.getProcessInstanceId()).singleResult();
      String businessKey = processInstance.getBusinessKey();//业务模型对象
      if (!StringUtils.isEmpty(businessKey)) {
        JSONObject jsonObject = findById(businessKey, taskService);
        if (jsonObject == null) continue;
        if (taskService.equalsIgnoreCase("expense")) {
          ExpenseReport expenseReport = JSON.parseObject(jsonObject.toJSONString(), ExpenseReport.class);
          if (expenseReport != null)
            TodoList.add(expenseReport);
        } else if (taskService.equalsIgnoreCase("applyassets")) {
          if (jsonObject != null) {
            ApplyAssetsReport applyassets = JSON.parseObject(jsonObject.toJSONString(), ApplyAssetsReport.class);
            if (applyassets != null)
              TodoList.add(applyassets);
          }

        }
      }
    }
    return TodoList;
  }

  public List<DailyWorkBaseVO> findDoneTasksMobile(String loginName, String queryService) {
    List<DailyWorkBaseVO> doneList = new ArrayList<>();
    String processKey = null;
    if (!StringUtils.isEmpty(queryService)) {
      if (queryService.equalsIgnoreCase("expense")) {
        processKey = "repair";
      } else if (queryService.equalsIgnoreCase("applyassets")) {
        processKey = "equipmentApply";
      }
    }
    List<HistoricTaskInstance> hisList = null;
    if (processKey != null) {
      hisList = historyService
        .createHistoricTaskInstanceQuery()
        .taskAssignee(loginName)
        .processDefinitionKey(processKey)
        .finished()
        .orderByHistoricTaskInstanceEndTime()
        .desc()
        .list();
    } else {
      hisList = historyService
        .createHistoricTaskInstanceQuery()
        .taskAssignee(loginName)
        .finished()
        .orderByHistoricTaskInstanceEndTime()
        .desc()
        .list();
    }
    for (HistoricTaskInstance instance : hisList) {
      String processInstanceId = instance.getProcessInstanceId();
      HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();
      Map<String, Object> processVariables1 = processInstance.getProcessVariables();
      String businessKey = processInstance.getBusinessKey();
      String taskService = (String) processVariables1.get("service");
      JSONObject jsonObject = findById(businessKey, taskService);
      if (jsonObject == null) continue;
      if (!StringUtils.isEmpty(queryService)) {
        if (!taskService.equalsIgnoreCase(queryService)) {
          continue;
        }
      }

      if (taskService.equalsIgnoreCase("expense")) {
        ExpenseReport expenseReport = JSON.parseObject(jsonObject.toJSONString(), ExpenseReport.class);
        doneList.add(expenseReport);
      } else if (taskService.equalsIgnoreCase("applyassets")) {
        ApplyAssetsReport applyassets = JSON.parseObject(jsonObject.toJSONString(), ApplyAssetsReport.class);
        if (applyassets != null)
          doneList.add(applyassets);
      }
    }
    return doneList;
  }

  /**
   * 历史实例包含正在执行实例
   */
  public List<DailyWorkBaseVO> appliedListMobile(String loginName, String queryService) {
    List<DailyWorkBaseVO> appliedList = new ArrayList<>();
    List<HistoricProcessInstance> Hilist = historyService.createHistoricProcessInstanceQuery().startedBy(loginName).includeProcessVariables().list();
    for (HistoricProcessInstance historicProcessInstance : Hilist) {
      Map<String, Object> processVariables1 = historicProcessInstance.getProcessVariables();
      String businessKey = historicProcessInstance.getBusinessKey();
      String taskService = (String) processVariables1.get("service");
      if (!StringUtils.isEmpty(queryService)) {
        if (!taskService.equalsIgnoreCase(queryService)) {
          continue;
        }
      }
      if (taskService != null) {
        JSONObject jsonObject = findById(businessKey, taskService);
        if (jsonObject == null) continue;
        if (taskService.equalsIgnoreCase("expense")) {
          if (!StringUtils.isEmpty(businessKey)) {
            ExpenseReport expenseReport = JSON.parseObject(jsonObject.toJSONString(), ExpenseReport.class);
            if (expenseReport != null)
              appliedList.add(expenseReport);
          }
        } else if (taskService.equalsIgnoreCase("applyassets")) {
          if (!StringUtils.isEmpty(businessKey)) {
            ApplyAssetsReport applyassets = JSON.parseObject(jsonObject.toJSONString(), ApplyAssetsReport.class);
            if (applyassets != null)
              appliedList.add(applyassets);
          }
        }
      }

    }
    return appliedList;
  }

  @Autowired
  private IApplycopyService applycopyService;

  public List<DailyWorkBaseVO> applyCopyList(String service, String loginName) {
    List<DailyWorkBaseVO> copyList = new ArrayList<>();
    Applycopy query = new Applycopy();
    query.setService(service);
    query.setLoginnamereceiver(loginName);
    List<Applycopy> list = applycopyService.selectApplycopyList(query);
    for (Applycopy applycopy : list) {
      if (!StringUtils.isEmpty(applycopy.getService())) {
        JSONObject jsonObject = findById(applycopy.getEntityid(), applycopy.getService());
        if (jsonObject == null) continue;
        if (applycopy.getService().equalsIgnoreCase("expense")) {
          ExpenseReport expenseReport = JSON.parseObject(jsonObject.toJSONString(), ExpenseReport.class);
          copyList.add(expenseReport);
        } else if (applycopy.getService().equalsIgnoreCase("applyassets")) {
          ApplyAssetsReport applyAssetsReport = JSON.parseObject(jsonObject.toJSONString(), ApplyAssetsReport.class);
          copyList.add(applyAssetsReport);
        }
      }

    }
    return copyList;
  }

  public JSONObject taskDetailMobile(String service, String taskId, String instanceId) {
    ProcessInstance processInstance = null;
    if (!StringUtils.isEmpty(taskId) && !StringUtils.isEmpty(instanceId)) {
      processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).includeProcessVariables().singleResult();
      if (processInstance == null) throw new RuntimeException("任务已结束");
    } else if (!StringUtils.isEmpty(taskId) && !StringUtils.isEmpty(instanceId)) {
      Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
      if (task != null) {
        processInstance = runtimeService.createProcessInstanceQuery().
          processInstanceId(task.getProcessInstanceId()).includeProcessVariables().singleResult();
      } else {
        throw new RuntimeException("无当前运行任务");
      }
    } else {
      throw new RuntimeException("任务id或者实例id为空");
    }
    String businessKey = processInstance.getBusinessKey();
    return getBaseVo(service, businessKey);
  }

  public JSONObject getBaseVo(String service, String bk) {
    StringBuilder sb = new StringBuilder();
    sb.append(dwUrl).append("/api/").append(service).append("/detail/").append(bk);
    String s1 = HttpClientUtil.doGet(sb.toString());
    if (!StringUtils.isEmpty(s1) && !s1.equalsIgnoreCase("-1")) {
      JSONObject jsonObject = JSON.parseObject(s1);
      JSONObject data = jsonObject.getJSONObject("data");
      return data;
    }
    return new JSONObject();
  }

  /**
   * 获取实例发起信息
   */
  public JSONObject getStartInfoByInstanceId(String instanceId) {
    String businessKey = null;
    String service =null;
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).includeProcessVariables().singleResult();
    if (processInstance != null) {
      businessKey = processInstance.getBusinessKey();
      service=(String) processInstance.getProcessVariables().get("service");
    } else {
      HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).includeProcessVariables().singleResult();
      if(historicProcessInstance !=null){
        businessKey = historicProcessInstance.getBusinessKey();
        service=(String) historicProcessInstance.getProcessVariables().get("service");
      }
    }
    JSONObject jsonObject = getBaseVo(service, businessKey);
    return jsonObject;
  }

  public void cancelApply(String service, String instanceId, String entityId) {
    processService.cancelApply(instanceId, "用户撤销");
    if (service.equalsIgnoreCase("expense")) {
      expenseReportService.cancelApply(entityId);
    } else if (service.equalsIgnoreCase("applyassets")) {
      applyAssetsReportService.cancelApply(entityId);
    }
  }

  public void submitApplyMobile(String id, String service, String loginName) {
    HashMap<String, Object> map = new HashMap<>();
    map.put("service", service);
    if (service.equalsIgnoreCase("expense")) {
      ExpenseReport expenseReport = new ExpenseReport();
      expenseReport.setId(id);
      expenseReportService.submitApplyMobile(expenseReport, loginName, "repair", map, service);
    } else if (service.equalsIgnoreCase("applyassets")) {
      ApplyAssetsReport applyAssetsReport = new ApplyAssetsReport();
      applyAssetsReport.setId(id);
      applyAssetsReportService.submitApplyMobile(applyAssetsReport, loginName, "equipmentApply", map, service);
    }
  }

  public ApproveProcessVo listHistory(String instanceId, String service, HistoricActivity historicActivity) {
    ApproveProcessVo approveProcessVo = new ApproveProcessVo();
    //发起人
    JSONObject jsonObject = getStartInfoByInstanceId(instanceId);
    approveProcessVo.setApplyUserName(jsonObject.getString("applyUserName"));
    approveProcessVo.setApplyTime(new Date(jsonObject.getLong("applyTime")));
    //已审批
    List<HistoricActivity> list = processService.selectHistoryList(instanceId, historicActivity);
    approveProcessVo.setList(list);
    //待审批
    approveProcessVo.setAssignName(jsonObject.getString("taskName"));
    approveProcessVo.setAssignTime(new Date(jsonObject.getLong("endTime")));
    return approveProcessVo;
  }

  @Autowired
  private MqttService mqttService;
  @Autowired
  private UserCacheService userCacheService;

  public void complete(String loginName, String taskId, String instanceId, String repair_titile,
                       String reason, String repair, Integer approved, String comment, String service,
                       HttpServletRequest request, String suspendState, String frontAssign) {
    HashMap<String, Object> map = new HashMap<>();
    map.put("comment", comment);
    map.put("approved", approved);
    map.put("service", service);
    map.put("frontAssign", frontAssign);
    map.put("suspendState", suspendState);

    processService.complete(
      "mobile",
      loginName,
      taskId,
      instanceId,
      "repair_titile",
      "reason",
      "repair",
      map,
      request);


  }

  public JSONObject findById(String id, String service) {
    StringBuilder sb = new StringBuilder();
    sb.append(dwUrl).append("/api/").append(service).append("/detail/").append(id);
    String detailStr = HttpClientUtil.doGet(sb.toString());
    if (detailStr != null && detailStr.startsWith("{")) {
      JSONObject jsonObject = JSON.parseObject(detailStr);
      if (jsonObject != null) {
        JSONObject data = jsonObject.getJSONObject("data");
        return data;
      }
    }
    return null;
  }

  public void update(String jsonObj, Integer type, String service) {
    ApplyAssetsReport applyAssetsReport = JSON.parseObject(jsonObj, ApplyAssetsReport.class);
    StringBuilder sb = new StringBuilder();
    if (type == 1) {//非空更新
      sb.append(dwUrl).append("/api/").append(service).append("/update/").append(applyAssetsReport.getId());
    } else {//空值也覆盖更新
      sb.append(dwUrl).append("/api/").append(service).append("/update");
    }
    JSONObject o = (JSONObject) JSONObject.toJSON(applyAssetsReport);
    log.error("更新数据库" + o.toJSONString());
    String s = HttpClientUtil.doPost(sb.toString(), o);
    if (StringUtils.isEmpty(s) || s.equalsIgnoreCase("-1")) {
      throw new RuntimeException("更新失败..");
    }
  }

  public void reCommit(String loginName, String service, String taskId, String instanceId, String modifyEntity, Integer approved, HttpServletRequest request) {

    update(modifyEntity, 2, service);

    HashMap<String, Object> map = new HashMap<>();
    map.put("comment", "");
    map.put("approved", approved);
    map.put("service", service);
    processService.complete(
      "mobile",
      loginName,
      taskId,
      instanceId,
      "repair_titile",
      "reason",
      "repair",
      map,
      request);
  }

  public void delegate(String taskId, String loginName, String instanceId, String delegateToUser) {
    processService.delegate(taskId, loginName, delegateToUser);
  }

  public void addApplyCopy(String instanceId, String service, String loginNameSender, String copyComment,
                           String loginNameReceivers) {
    if (service.equalsIgnoreCase("expense")) {
      expenseReportService.addApplyCopy(instanceId, loginNameSender, copyComment, loginNameReceivers);
    }
  }

  @Autowired
  private IProjectUsersService projectUsersService;

  public Map<String, List<Long>> getAuthIds(String loginName) {
    Map<String, List<Long>> map = new HashMap<>();
    List<Long> uIds = new ArrayList<>();
    //返回role_key,权限id
    SysUser sysUser = userMapper.selectUserByLoginName(loginName);
    List<SysRole> roles = sysUser.getRoles();
    if (roles != null && roles.size() > 0) {
      List<String> roleKeys = new ArrayList<>();
      for (SysRole role : roles) {
        String roleKey = role.getRoleKey();
        if (!StringUtils.isEmpty(roleKey)) {
          roleKeys.add(roleKey);
        }
      }
      if (roleKeys.contains("admin")) {
        map.put("admin", uIds);
        return map;
      } else if (roleKeys.contains("projectManager")) { //拉取该项目下的所有成员id
        uIds.clear();
        //默认一个账户只关联一个项目
        ProjectUsers projectUsers = new ProjectUsers();
        projectUsers.setLoginName(loginName);
        Long projectInfoId = 0L;
        List<ProjectUsers> list1 = projectUsersService.selectProjectUsersList(projectUsers);
        if (list1 != null && list1.size() > 0) {
          ProjectUsers tmp = list1.get(0);
          projectInfoId = tmp.getProjectinfoid();
        }

        projectUsers = new ProjectUsers();
        projectUsers.setProjectinfoid(projectInfoId);
        List<ProjectUsers> list = projectUsersService.selectProjectUsersList(projectUsers);
        if (list != null) {
          for (ProjectUsers projectUsers1 : list) {
            uIds.add(projectUsers1.getUserid());
          }
        }
        map.put("projectManager", uIds);
        return map;
      } else {//只授权他的直接孩子节点和自己节点
        uIds.clear();
        List<Long> list = userMapper.findSonIdsByPid(sysUser.getUserId());
        uIds.add(sysUser.getUserId());
        if (list != null) {
          uIds.addAll(list);

        }
        map.put("normal", uIds);
        return map;
      }
    }
    map.put("normal", uIds);
    return map;
  }

  public JSONObject findByProcessInstanceId(String processInstanceId, String service) {
    StringBuilder sb = new StringBuilder();
    sb.append(dwUrl).append("/api/").append(service).append("/findOneByInstanceId/").append(processInstanceId);
    String detailStr = HttpClientUtil.doGet(sb.toString());
    JSONObject jsonObject = JSON.parseObject(detailStr);
    JSONArray data = jsonObject.getJSONArray("data");
    if (data != null && data.size() > 0) {
      return data.getJSONObject(0);
    }
    return null;
  }

  public int getProjectMaxRole(SysUser sysUser) {
    List<Long> pmList = new ArrayList<>();
    List<Long> areaLeaderList = new ArrayList<>();
    pmList.add(112l);//项目经理
    areaLeaderList.add(115l);//片区管理
    List<Long> roleIds = new ArrayList<>();
    if (sysUser.getRoles() != null) {
      for (SysRole sysRole : sysUser.getRoles()) {
        roleIds.add(sysRole.getRoleId());
      }
    }
    pmList.retainAll(roleIds);
    areaLeaderList.retainAll(roleIds);

    if (pmList.size() > 0) {
      return 3;
    } else if (areaLeaderList.size() > 0) {
      return 2;
    } else {
      return 1;
    }
  }

}
